/**
 * @Copyright：<a href="http://www.wisesoft.net.cn">四川川大智胜系统集成有限公司</a>
 * @Author: <a href="mailto:fxsen@foxmail.com">Fxsen</a>
 * @CreateTime: 2022年08月06日  17:52
 */
package com.fxsen.commons.utils;

import java.math.BigDecimal;

/**
 * 浮点工具类
 *@Author: <a href="mailto:fxsen@foxmail.com">Fxsen</a>
 *@CreateTime: 2022年08月06日  17:52
 */
public class DecimalUtils {

    //	运算精度
    private static final int DEF_DIV_SCALE = 10;
    /**
     * 加法
     * @param v1 第一操作数
     * @param v2 第二操作数
     * @return 和
     */
    public static double add(double v1, double v2){
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.add(b2).doubleValue();
    }

    /**
     * 减法
     * @param v1 第一操作数
     * @param v2 第二操作数
     * @return 差
     */
    public static double sub(double v1, double v2){
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.subtract(b2).doubleValue();
    }

    /**
     * 乘法
     * @param v1 第一操作数
     * @param v2 第二操作数
     * @return 积
     */
    public static double mul(double v1, double v2){
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.multiply(b2).doubleValue();
    }

    /**
     * 除法
     * 使用默认精度进行运算
     * @param v1 第一操作数
     * @param v2 第二操作数
     * @return 商
     */
    public static double div(double v1, double v2){
        return div(v1, v2, DEF_DIV_SCALE);
    }

    /**
     * 除法
     * 使用指定精度进行运算
     * @param v1 第一操作数
     * @param v2 第二操作数
     * @param scale 运算精度
     * @return 商
     */
    public static double div(double v1, double v2, int scale){
        if(scale<0){
            throw new IllegalArgumentException(
                    "The scale must be a positive integer or zero");
        }
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
    }
    public static int divToInt(double v1, double v2, int scale){
        if(scale<0){
            throw new IllegalArgumentException(
                    "The scale must be a positive integer or zero");
        }
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).intValue();
    }

    /**
     * 四舍五入法
     * @param v 要四舍五入的数字
     * @param scale 精度
     * @return 结果
     */
    public static double round(double v, int scale){
        if(v == 0) return 0;
        if(scale<0){
            throw new IllegalArgumentException(
                    "The scale must be a positive integer or zero");
        }
        BigDecimal b = new BigDecimal(Double.toString(v));
        BigDecimal one = new BigDecimal("1");
        return b.divide(one, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
    }


    /**
     * 四舍五入法
     * @param v 要四舍五入的数字
     * @return 结果
     */
    public static Integer round(double v){

        BigDecimal b = new BigDecimal(Double.toString(v));
        BigDecimal one = new BigDecimal("1");
        return b.divide(one, 0, BigDecimal.ROUND_HALF_UP).intValue();
    }

    /**
     * 上取整
     * @param v 要上取整的数字
     * @return 结果
     */
    public static Integer roundUp(double v){

        BigDecimal b = new BigDecimal(Double.toString(v));
        BigDecimal one = new BigDecimal("1");
        return b.divide(one, 0, BigDecimal.ROUND_UP).intValue();
    }

    /**
     * 下取整
     * @param v 要下取整的数字
     * @return 结果
     */
    public static Double roundUp(double v, int scale){

        BigDecimal b = new BigDecimal(Double.toString(v));
        BigDecimal one = new BigDecimal("1");
        return b.divide(one, scale, BigDecimal.ROUND_UP).doubleValue();
    }

    /**
     * 下取整
     * @param v 要下取整的数字
     * @return 结果
     */
    public static Integer roundDown(double v){

        BigDecimal b = new BigDecimal(Double.toString(v));
        BigDecimal one = new BigDecimal("1");
        return b.divide(one, 0, BigDecimal.ROUND_DOWN).intValue();
    }

    /**
     * 下取整
     * @param v 要下取整的数字
     * @return 结果
     */
    public static Double roundDown(double v, int scale){

        BigDecimal b = new BigDecimal(Double.toString(v));
        BigDecimal one = new BigDecimal("1");
        return b.divide(one, scale, BigDecimal.ROUND_DOWN).doubleValue();
    }

    /**
     * 将一个数近似到最近的千位数
     * @param v
     * @return
     */
    public static Integer round2Thousand(double v)
    {
        int num = round(v);
        num += (1000 - num % 1000);
        return num;
    }

    /**
     * 求平均数
     * @param nums
     * @return
     */
    public static Double avg(Double...nums)
    {
        if(nums != null && nums.length > 0)
        {
            double total = 0;
            for(int i = 0; i < nums.length; i++)
            {
                total += nums[i];
            }
            return div(total, nums.length);
        }
        return 0d;
    }

    /**
     * 求一组数据的标准方差
     * @param nums
     * @return
     */
    public static Double stdEv(Double...nums)
    {
        if(nums != null && nums.length > 0)
        {
            double avg = avg(nums);
            double total = 0;
            for(int i = 0; i < nums.length; i++)
            {
                total += Math.pow(nums[i] - avg, 2);
            }
            return Math.sqrt(div(total, nums.length - 1));
        }
        return 0d;
    }

    /**
     * 求一组数据的标准方差
     * @param nums
     * @return
     */
    public static Double stdEvp(Double...nums)
    {
        if(nums != null && nums.length > 0)
        {
            double avg = avg(nums);
            double total = 0;
            for(int i = 0; i < nums.length; i++)
            {
                total += Math.pow(nums[i] - avg, 2);
            }
            return Math.sqrt(div(total, nums.length));
        }
        return 0d;
    }
    public static int toRoundInt(String str) {
        BigDecimal bigDecimal = new BigDecimal(str).setScale(0, BigDecimal.ROUND_HALF_UP);
        /*String val = "";
        if (bigDecimal == null) {
            return val;
        } else {
            val = String.valueOf(bigDecimal);
        }
        if (val.indexOf(".") > 0) {
            // 去掉后面无用的零
            val = val.replaceAll("0+?$", "");
            // 如小数点后面全是零则去掉小数点
            val = val.replaceAll("[.]$", "");
        }
        */
        return bigDecimal.intValue();
    }
    /**
     * 百分比转换（*100）
     * @param str
     * @return
     * @Description:
     * @Date: 2022年1月5日 上午11:33:54
     * @author chen.qi
     */
    public static int convertPer(String str) {
        BigDecimal bigDecimal = new BigDecimal(str);
        bigDecimal = bigDecimal.multiply(new BigDecimal(100));
        return bigDecimal.intValue();
    }
    public static void main(String[] args) {
        System.out.println(stdEvp(10d, 15d, 20d, 25d, 30d));
    }
}
